package com.sunday.redisson.lock;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.InitializingBean;

import java.util.ArrayList;
import java.util.List;

/**
 * 分布式锁
 *
 * @author zsy
 * @since 2022/10/20
 */
@Slf4j
@RequiredArgsConstructor
public class DistributedLock implements InitializingBean {

    private final RedissonClient redissonClient;

    private static DistributedLock distributedLock;

    @Override
    public void afterPropertiesSet() {
        distributedLock = this;
    }

    public static DistributedLock getInstances() {
        return distributedLock;
    }

    private static final ThreadLocal<List<RLock>> LOCKS = ThreadLocal.withInitial(ArrayList::new);

    public static boolean lock(String token) {
        RLock lock = getInstances().redissonClient.getSpinLock(token);
        if (lock.tryLock()) {
            addLock(lock);
            log.info("[Redis Lock] successful -> key : {}", token);
            return true;
        }
        log.info("[Redis Lock] failure -> key : {}", token);
        return false;
    }

    public static void addLock(RLock lock) {
        LOCKS.get().add(lock);
    }

    public static void unlock() {
        /** 不论放锁情况如何 ，不能影响到其他需要放锁的对象 */
        LOCKS.get().stream().forEach(lock -> {
            try {
                lock.unlock();
                log.info("[Redis Lock] release complete -> key : {}", lock.getName());
            } catch (Exception e) {
                log.error("[Redis Lock] release error -> key : {} , cause : {}", lock.getName(), e.toString(), e);
            }
        });
        LOCKS.get().clear();
    }

}